package org.xt.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.QueryResult;
import org.nutz.dao.Sqls;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.random.R;
import org.nutz.trans.Atom;
import org.nutz.trans.Trans;
import org.xt.constants.Res;
import org.xt.entity.Department;
import org.xt.entity.Permission;
import org.xt.entity.Role;
import org.xt.entity.RolePermission;
import org.xt.entity.User;
import org.xt.entity.UserRole;
import org.xt.vo.UserVo;

@IocBean(name="userService")
public class UserService {
	@Inject
	private Dao dao;
	
	public User create(User user){
		String salt = R.sg(8).next() + "-" + user.getPassword();
		String md5Psd = Lang.md5(user.getPassword() + salt);
		user.setPassword(md5Psd);
		user.setSalt(salt);
		user.setCreateTime(new Date());
		user.setUpdateTime(new Date());
		user = dao.insert(user);
		return user;
	}
	public QueryResult finds(int page, int size, int departmentId, String search){
		Cnd cnd = Cnd.where("id", ">", "-1000");
		if(departmentId != 0){
			cnd.and("departmentId", "=", departmentId);
		}
		if(search != null && !"".equals(search)){
			cnd.and("username", "like", "%" + search + "%").or("no", "like", "%" + search + "%");
		}
		Pager pager = dao.createPager(page, size);
		pager.setRecordCount(dao.count(User.class, cnd));
		List<User> users = dao.query(User.class, cnd, pager, "id|departmentId|no|username|createTime|updateTime");
		List<UserVo> userVos = new ArrayList<>();
		for(User user : users){
			UserVo userVo = new UserVo();
			userVo.setUser(user);
			Department department = dao.fetch(Department.class, user.getDepartmentId());
			userVo.setDepartment(department);
			userVos.add(userVo);
		}
		return new QueryResult(userVos, pager);
	}
	public boolean changePassword(int id, String password){
		User user = dao.fetch(User.class, id);
		String md5Psd = Lang.md5(password+user.getSalt());
		user.setPassword(md5Psd);
		if(dao.update(user) > 0){
			return true;
		}else{
			return false;
		}
	}
	public int delete(int id){
		Trans.exec(new Atom() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				dao.delete(User.class, id);
				Sql sql = Sqls.create("DELETE FROM tb_user_role WHERE userId=@id");
				sql.params().set("id", id);
				dao.execute(sql);
			}
		});
		return 1;
	}
	public int addRole(int userId, int... roleIds){
		int sum = 0;
		for(int rid: roleIds){
			if(dao.fetch(User.class, userId) == null || dao.fetch(Role.class, rid) == null){
				continue;
			}
			UserRole ur = new UserRole();
			ur.setUserId(userId);
			ur.setRoleId(rid);
			ur.setCreateTime(new Date());
			ur.setUpdateTime(new Date());
			try{
				ur = dao.insert(ur);
				if(ur != null){
					sum ++;
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return sum;
	}
	public int removeRole(int userId, int... roleIds){
		int sum = 0;
		for(int rid: roleIds){
			sum += dao.deletex(UserRole.class, userId, rid);
		}
		return sum;
	}
	public User findByNo(String no){
		return dao.fetch(User.class, no);
	}
	public Set<Role> findRolesByNo(String no){
		User user = findByNo(no);
		List<UserRole> urs = dao.query(UserRole.class, Cnd.where("userId", "=", user.getId()));
		Set<Role> roles = new HashSet<Role>();
		for(UserRole ur : urs){
			roles.add(dao.fetch(Role.class, ur.getRoleId()));
		}
		return roles;
	}
	
	public QueryResult findRolesNotUser(int userId, String serach, int page, int size){
		List<UserRole> urs = dao.query(UserRole.class, Cnd.where("userId", "=", userId));
		if(urs!= null && urs.size() > 0){
			int[] rids = new int[urs.size()];
			for(int i = 0; i < urs.size(); i ++){
				rids[i] = urs.get(i).getRoleId();
			}
			Criteria cri = Cnd.cri();
			
			cri.where().andLike("descript", serach).andNotIn("id", rids);
			Pager pager = dao.createPager(page, size);
			pager.setRecordCount(dao.count(Role.class, cri));
			List<Role> rs = dao.query(Role.class,cri, pager);
			return new QueryResult(rs, pager);
		}else{
			Pager pager = dao.createPager(page, size);
			pager.setRecordCount(dao.count(Role.class, Cnd.where("descript", "like", "%" + serach + "%")));
			List<Role> rs = dao.query(Role.class, Cnd.where("descript", "like", "%" + serach + "%"), pager);
			return new QueryResult(rs, pager);
		}
		
	}
	public List<Role> findRolesByUser(int userId){
		List<UserRole> urs = dao.query(UserRole.class, Cnd.where("userId", "=", userId));
		if(urs!= null && urs.size() > 0){
			List<Role> rs = new ArrayList<>();
			for(int i = 0; i < urs.size(); i ++){
				rs.add(dao.fetch(Role.class, urs.get(i).getRoleId()));
			}
			return rs;
		}
		return null;
	}
	public Set<Permission> findPermissionByNo(String no){
		User user = findByNo(no);
		List<UserRole> urs = dao.query(UserRole.class, Cnd.where("userId", "=", user.getId()));
		Set<Permission> permissions = new HashSet<>();
		for(UserRole ur : urs){
			Role role = dao.fetch(Role.class, ur.getRoleId());
			List<RolePermission> rps = dao.query(RolePermission.class, Cnd.where("roleId", "=", role.getId()));
			for(RolePermission rp : rps){
				permissions.add(dao.fetch(Permission.class, rp.getPermissionId()));
			}
		}
		return permissions;
	}
}
